﻿#Region "Copyright"

' Copyright 2007 Ben Reichelt - http://benreichelt.net
' 
' Licensed under the Apache License, Version 2.0 (the "License");
' you may not use this file except in compliance with the License.
' You may obtain a copy of the License at
' 
'     http://www.apache.org/licenses/LICENSE-2.0
' 
' Unless required by applicable law or agreed to in writing, software
' distributed under the License is distributed on an "AS IS" BASIS,
' WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
' See the License for the specific language governing permissions and
' limitations under the License.


#End Region

Imports System.CodeDom.Compiler
Imports System.Reflection
Imports Microsoft.CSharp


Public Class CustomTasks

    Private _context As AppContext
    Private _fs As IFileSystem

    Public Sub New(ByVal context As AppContext, ByVal fs As IFileSystem)
        _context = context
        _fs = fs
    End Sub

    Public Function FindAll() As List(Of IMetaDataTask)

        Dim list As New List(Of IMetaDataTask)

        Dim custom As Assembly = CreateCustomAssembly()
        If custom Is Nothing Then
            Return list
        End If

        For Each t As Type In custom.GetTypes
            If t.GetInterfaces().Contains(GetType(IMetaDataTask)) Then
                list.Add(CType(Activator.CreateInstance(t), IMetaDataTask))
            End If
        Next

        list.Sort()

        _context.Logger.WriteLine("Found " & list.Count & " custom task types")

        Return list

    End Function

    Public Function GetCustomCodeFiles() As List(Of String)

        Dim dir As String = "CustomTasks"
        If Not _fs.DirectoryExists(dir) Then
            _context.Logger.WriteLine("Creating directory ""CustomTasks""")
            _fs.CreateDirectory(dir)
            Return New List(Of String)
        End If

        Dim files As List(Of String) = _fs.GetFilesInDirectory(dir, "*." & _context.CodeFileExtension)
        Return files
    End Function

    Private Function CreateCustomAssembly() As Assembly

        Dim files As List(Of String) = GetCustomCodeFiles()
        If files.Count = 0 Then
            _context.Logger.WriteLine("0 custom task files found, no tasks will be applied")
            Return Nothing
        End If

        _context.Logger.WriteLine("Found " & files.Count & " custom task files")
        
        Dim codeDom As CodeDomProvider

        If _context.Language = Language.VB Then
            codeDom = New VBCodeProvider
        Else
            codeDom = New CSharpCodeProvider
        End If

        Dim options As New CompilerParameters
        options.ReferencedAssemblies.Add("mscorlib.dll")
        options.ReferencedAssemblies.Add("System.dll")
        options.ReferencedAssemblies.Add("System.Xml.dll")
        options.ReferencedAssemblies.Add("System.Data.dll")
        options.ReferencedAssemblies.Add("SqlPlastic.exe")
        options.CompilerOptions = "/target:library"
        If _context.Language = Language.VB Then
            options.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll")
            options.CompilerOptions &= " /imports:SqlPlastic"
        End If

        options.GenerateInMemory = True
        options.GenerateExecutable = False
        options.IncludeDebugInformation = True

        Dim results As CompilerResults = codeDom.CompileAssemblyFromFile(options, files.ToArray)

        If results.Errors.Count > 0 Then
            For Each err As CompilerError In results.Errors
                Console.WriteLine(err.ErrorText)
            Next
            Return Nothing
        End If

        Return results.CompiledAssembly

    End Function

End Class
